:where()
函式接受一個選擇器列表作為參數,允許你編寫更少的代碼並同時設置它們的樣式。本篇文章我們來討論 :where()
的偽類函式,並示範如何在生產環境中使用它。我們將回顧與 :where()
函式相關的疊加、優先級和安全性;另外我們還研究一些特定的範例,並討論它與 :is()
函式的差別!
:where()
?根據MDN,:where()
是一個CSS 偽類函數選擇器,它接受一個選擇器列表作為參數,並將給定的樣式應用於該列表中的任何元素,因此 :where()
對於縮短一個較長的選擇器列表非常有用。
在 CSS 中,當多個元素同時應用相同的樣式規則時,我們通常會編寫一長串以逗號分隔的選擇器。
下面是一個例子,我們將相同的樣式應用到 header、main 元素和 footer 元素中的所有 a 標籤:
header a:hover,
main a:hover,
footer a:hover {
color: green;
text-decoration: underline;
}
在上面的代碼片段中,我們只選擇了三個元素,但是如果有大量的元素和選擇器,代碼將開始看起來不整潔,並且可能變得難以閱讀和理解。這就是 :where()
偽類函數發揮作用的地方。
下面是上面的例子使用 :where()
函數的樣子:
:where(header, main, footer) a:hover {
color: red;
text-decoration: underline;
}
當瀏覽器到達該代碼片段時,該代碼指示瀏覽器查找 header、main 和 footer 選擇器,並定位這些選擇器中的所有 a 標籤。
當用戶將鼠標懸停在任何這些 a 標籤上時,瀏覽器應該應用指定的樣式,在本例中為文字顏色紅色與下劃線。這個偽類函數使我們能夠以更短、更容易理解的方式編寫一個很長的選擇器列表。
:where()
函數使用 :where()
函數,我們可以以多種方式和組合對元素進行分組。
我們可以將 :where()
函數放在選擇器的開頭、中間或結尾。
下面是一個有多個選擇器和樣式的例子:
/* first list */
header a:hover,
main a:hover,
footer a:hover {
color: green;
text-decoration: underline;
}
/* second list */
article header > p,
article footer > p{
color: gray;
}
/* third list */
.dark-theme button,
.dark-theme a,
.dim-theme button,
.dim-theme a{
color: purple;
}
下面是相同的代碼,用 :where()
函數重寫:
/* first list */
:where(header, main, footer) a:hover {
color: red;
text-decoration: underline;
}
/* second list */
article :where(header, footer) > p {
color: gray;
}
/* third list */
.dark-theme :where(button, a) {
color: purple;
}
.dim-theme :where(button, a) {
color: purple;
}
在第一個列表中,我們指定「紅色」和「下劃線」樣式應應用於懸停時的 header 元素、main 元素和 footer 元素。在第二個列表中,我們指定 article元素、header元素 和 footer 元素應該使用灰色樣式。
為了更清晰,我們將第三個列表分為兩個 :where()
函數。在這個列表中,我們指定 .dark-theme、.dim-theme 裡的 button 和 a 元素的樣式應該是紫色。
現在,我們將進一步減少第三個列表函數,將它們變成一個 :where()
函數:
/* 堆疊 */
:where(.dark-theme, .dim-theme) :where(button, a) {
color: purple;
}
這種減少複雜選擇器列表的方式稱為疊加。
:where()
選擇器的優先級:where()
函數選擇器的優先級總是零。
因此,以該函數為目標的任何元素也會自動獲得 0 的優先級。這使我們能夠輕鬆地取消任何元素的樣式。
下面是一個 HTML 有序列表的例子:
<div>
<h2>First list no class</h2>
<ol>
<li>List Item 1</li>
<li>List Item 2</li>
</ol>
</div>
<div>
<h2>Second list with class</h2>
<ol class="second-list">
<li>List Item 1</li>
<li>List Item 2</li>
</ol>
</div>
<div>
<h2>Third list with class</h2>
<ol class="third-list">
<li>List Item 1</li>
<li>List Item 2</li>
</ol>
</div>
在上面的代碼片段中,有三個有序列表,每個列表中有兩個項。第二個和第三個列表有一個給定的類,而第一個列表沒有。
沒有任何樣式,我們可以看到每個列表是按數字順序排列的:
現在讓我們添加一些樣式:
:where(ol[class]) {
list-style-type: none;
}
在上面的代碼片段中,我們使用 :where()
偽類函數來選擇應用了類的所有 ol 標籤。
下面,我們看到第二個和第三個列表,它們都有一個類,被 :where()
函數作為目標,並刪除了它們的 list-style-type:
現在,讓我們添加一些額外的樣式:
:where(ol[class]) {
list-style-type: none;
}
.second-list {
list-style-type: disc;
}
只針對使用類名的第二個列表,我們可以看到它現在顯示為項目符號,而第三個列表仍然沒有列表樣式類型:
你可能會想,"這不應該是這樣嗎,因為新的樣式寫在 :where()
函數樣式下面?"不,它不是,我們一會兒就會看到。
讓我們看看當我們把剛剛添加的代碼移到代碼塊的頂部,並把 :where()
函數部分移到底部時,會發生什麼:
.second-list {
list-style-type: disc;
}
:where(ol[class]) {
list-style-type: none;
}
注意樣式仍然沒有改變:
記住:
:where()
函數的優先級為零。
:where()
選擇器的安全性對於選擇器列表,如果瀏覽器不能識別列表中的一個選擇器,則整個選擇器列表將被視為無效,並且它們的樣式將不會被應用。然而對於 :where()
偽類函數就不是這樣了。
如果 :where()
函數中的元素是無效選擇器的目標,則該元素將不會獲得任何樣式。其餘的元素仍然會被設置樣式。:where()
函數將跳過無效的選擇器到下一個(有效)選擇器。
這就是為什麼 :where()
被稱為安全的選擇器。
在下面的例子中,:unsupported
對於許多瀏覽器來說是無效的選擇器。下面的代碼將被正確解析,並且仍然會匹配 :valid
選擇器,即使在不支持 :unsupported
選擇器的瀏覽器中,如下所示:
:where(:valid, :unsupported) {
/* ... */
}
而在不支持 :unsupported
選擇器的瀏覽器中,以下代碼將被忽略,即使它們支持 :valid
選擇器:
:valid, :unsupported {
/* ... */
}
:where()
函數的特殊用例在一些特殊的用例中,:where()
函數可能是一個有用的工具,但也有一些情況下應該避免使用它。
使用 :where()
偽類函數時出現的幾乎所有問題都歸結為優先級。
因為 :where()
的優先級為零
,我們需要非常小心地選擇何時何地使用這個函數。
首先,讓我們看看幾個用例,在這些用例中 :where()
可能特別有用。
然而,根據 CSS 重置中使用的元素或元素組的選擇器的簡單性或複雜性,稍後在代碼中可能很難覆蓋初始樣式。
例如,假設我們將網站上的所有的 a 標籤設置為綠色。
然後我們稍後決定將所有 header 裡的 a 標籤的樣式設置為灰色。
由於在 CSS 重置中選擇的複雜性,新的(灰色)樣式不會被應用。
重置中的選擇器比後面代碼中僅針對 header 裡的 a 標籤使用的選擇器具有更高階的優先級,因此沒有應用灰色樣式。
現在,如果我們將 :where()
偽類函數添加到 CSS 重置中,這將自動為重置中的所有元素賦予零的優先級。
這使得我們以後更容易更改樣式,而不必擔心優先級衝突。
如果想要刪除或取消樣式或降低一個或一組元素的優先級,則 :where()
函數非常有用。
如果要確保一個元素或元素集的樣式或優先級在未來的任何時候都不會改變,那麼不要使用 :where()
偽類。
:is()
?:is()
函數的運行方式幾乎與 :where()
函數相同。
你可以用它來簡化複雜的選擇器,也可以把它放在選擇器的開頭、中間或結尾,就像 :where()
函數一樣。
它也是安全的,就像 :where()
函數一樣。因此,當其中一個選擇器無效時,瀏覽器將忽略該選擇器,但有效選擇器的樣式將添加到所選元素中。
:where()
和 :is()
函數的區別?這兩個函數的區別在於 :where()
函數的優先級總是零
,則 :is()
函數的優先級取決於其最特定參數的優先級
。
例如,讓我們看看 header 元素中的段落文本:
<header>
<p>This is a paragraph text.</p>
</header>
然後,讓我們嘗試使用四種不同的選擇器來改變文本顏色:
header p {
color: blue;
}
:is(header, section) p {
color: green;
}
p {
color: blue;
}
:where(header, section) p {
color: blue;
}
第一個選擇器將文本的顏色設置為藍色。使用 :is()
的第二個選擇器與第一個選擇器具有相同的優先級,但由於它位於第一個選擇器之後,因此它將文本顏色從藍色更改為綠色。第三個選擇器的優先級低於第一個和第二個選擇器,對文本沒有影響。最後是第四個,它使用 :where()
函數對文本沒有影響,因為它的零優先級。
所有瀏覽器,無論是桌面瀏覽器還是移動瀏覽器,都完全支持 :where()
函數,包括對其安全特性的支持。因此,你不必擔心你的樣式是否會在瀏覽器中正確呈現。
作者:Wayne (偉恩)
連結:https://wayne-blog.com/
來源:Wayne's blog | 偉恩的部落格 | 技術博客